<?php

/**
 * Parcl
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://parcl.com/license
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@parcl.com so we can send you a copy immediately.
 *
 * @category parcl
 * @package parcl-core
 * @subpackage events
 * @copyright Copyright (c) 2006-2011 Mikael Knutsson (http://mikn.me)
 * @license http://parcl.com/license New BSD License
 */

namespace Parcl\Core {

	if(PARCL_EXEC !== 1) {
		die('<h1>Incorrect Access</h1>You cannot access this file directly.<br/>' .
			 'If you got this error message by clicking a link on the site,' .
			 'please notify the webmaster as soon as possible.');
	}

	/**
	 * Purpose     : Define all common functions for classes wanting to be able to
					 trigger events.
	 * Description : This class defines all functions and variables needed for an event
					 enabled class. It was defined abstract because it must not be
					 instanciated by itself.
	 * - Construct -
	 * Input       : None.
	 * Output      : Not applicable.
	 * Description : Grabs all singletons and pulls them down in protected class variables.
	 * Errors      : None.
	 * Assumptions : That the singletons are available.
	 * Dev Notes   : None at the moment.
	 */

	abstract class Events {
		protected $events = null;
		protected $eventHandlers = null;
		protected $registeredEvents = null;

		protected function __construct() {
			$this->events = EventCollection::GetInstance();
			$this->eventHandlers = EventHandlerCollection::GetInstance();
			$this->registeredEvents = RegisterEvents::GetInstance();
		}

		/**
		 * Input       : $eventName: String name of the event that is being triggered.
						 $args: The arguments being passed to the callback of the event. Optional.
		 * Output      : None.
		 * Description : This is simply a wrapper for EventHandlerCollection::RaiseEvent
						 to allow no arguments to be specified, and to not have to type $this
						 every time you want to trigger an event.
		 * Errors      : No error conditions have been defined.
		 * Assumptions : That $eventName is a string and $args is an array if specified.
						 Also that it is called from within another class.
		 * Dev Notes   : I'm not sure if we should add checks on $eventName and $args or not.
		 */

		final protected function triggerEvent($eventName, $args = array()) {
			$this->eventHandlers->RaiseEvent($eventName, $this, $args);
			return true;
		}

		/**
		 * Input       : $namespace: The namespace to reset Events and Handlers for.
		 * Output      : Returns boolean true if successful.
		 * Description : This function resets a namespace, both the triggered status on
						 the events triggered, and the handlers connected to the events.
		 * Errors      : No direct errors.
		 * Assumptions : That __construct has been called.
		 * Dev Notes   : Made it protected since it's not supposed to be called outside
						 directly event driven classes.
		 */

		final protected function resetNamespace($namespace) {
			$resetEvents = $this->events->ResetTriggeredNS($namespace);
			$this->eventHandlers->ResetHandlers($resetEvents);
			return true;
		}

		/**
		 * Input       : $handler: The event handler to be registered.
		 * Output      : None.
		 * Description : This function checks if the handler is really a handler, and
						 if the event is registered. Then adds the handler to the collection.
		 * Errors      : An error is thrown if an event handler is added to an event
						 that hasn't been registered.
		 * Assumptions : That Events has had its __construct called.
		 * Dev Notes   : Don't think the assumption is too far-fetched.
		 */

		final private function regEventHandler($handler) {
			EventHandler::IsEventHandler($handler);
			if(!$this->events->Contains(new Event($handler->GetEventName()))) {
				throw new EventException('Tried to add Event Handler "' . print_r($handler, true) .
										  '" to a non-registered event.', EventException::HANDLER);
			}
			$this->eventHandlers->Add($handler);
			return true;
		}

		final public function AddEventHandler($event, $callback) {
			$this->regEventHandler(new EventHandler(new Event($event),
													  $callback));
			return true;
		}
	}
}